package com.cqc.jdk8.Jutil.concurrent.threadPoolExecutor.exception;


import java.util.concurrent.BlockingQueue;
import java.util.concurrent.FutureTask;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

/**
 * @author cui
 * @date 2023/11/10 21:19
 * @description
 **/
public class TimeThreadPoolExecutor extends ThreadPoolExecutor {


    //开始时间
    private final ThreadLocal<Long> threadLocal = new ThreadLocal<>();
    //统计任务数
    private final AtomicLong taskCountAtomic = new AtomicLong();
    //线程池运行 总时间
    private final AtomicLong totalTimeAtomic = new AtomicLong();

    public TimeThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
    }

    @Override
    protected void beforeExecute(Thread t, Runnable r) {
        super.beforeExecute(t, r);
        threadLocal.set(System.currentTimeMillis());
    }

    @Override
    protected void afterExecute(Runnable r, Throwable t) {

        try {
            long endTime = System.currentTimeMillis();
            Long startTime = threadLocal.get();
            // 一个任务花费的时长
            long taskTime = endTime - startTime;
            //添加调用次数
            taskCountAtomic.incrementAndGet();
            //添加时间
            totalTimeAtomic.addAndGet(taskTime);
            System.out.println(String.format("Thread %s: end %s ,time=%dms", t, r, taskTime));
        } finally {
            super.afterExecute(r, t);
        }
        //如果Thread发生异常
        if (null != t) {
            t.printStackTrace();
        }
        if (r instanceof FutureTask) {
            try {
                FutureTask futureTask = (FutureTask) r;
                Object o = futureTask.get();
                t.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }


    @Override
    protected void terminated() {
        try {
            long totalTime = totalTimeAtomic.get();
            long taskCount = taskCountAtomic.get();
            System.out.println(String.format("totalTime=%dms,taskCount=%d,avage time is %dms", totalTime, taskCount, totalTime / taskCount));
        } finally {
            super.terminated();
        }
    }
}
